/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2020年10月5日
 */
package com.massyframework.beanskin.maven.plugin.ras;

import java.io.File;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Objects;

/**
 * 提供从keyStore或者cer文件加载RSA密钥的能力
 * 
 * @author huangkh
 *
 */
public interface RSAKeyReader {

	/**
     * 从{@code privateKey}提取私钥字符串
     * @param privateKey {@link PrivateKey}
     * @return {@link String}
     * @throws IOException io读写时抛出的例外
     */
    String getString(PrivateKey privateKey) throws IOException;

    /**
     * 从{@code publicKey}提取公钥字符串
     * @param publicKey {@link PublicKey}
     * @return {@link String}
     * @throws IOException io读写时抛出的例外
     */
    String getString(PublicKey publicKey) throws IOException;
    
   
    /**
     * 从{@code certificate}提取证书字符串
     * @param certificate {@link X509Certificate}, 509证书
     * @return {@link String}
     * @throws CertificateEncodingException
     */
    default String getString(X509Certificate certificate) throws CertificateEncodingException {
        Base64.Encoder encoder = Base64.getMimeEncoder(64, SignatureUtils.LINE_SEPARATOR.getBytes());
        byte[] rawCrtText = certificate.getEncoded();
        String encodedCertText = new String(encoder.encode(rawCrtText));
        return SignatureUtils.BEGIN_CERT.concat(SignatureUtils.LINE_SEPARATOR)
                    .concat(encodedCertText)
                    .concat(SignatureUtils.LINE_SEPARATOR)
                    .concat(SignatureUtils.END_CERT);
    }
    
    /**
     * 从{@link keyStore}中提取{@link alias}的私钥
     * @param keystore {@link KeyStore}
     * @param alias {@link String}, key的别名
     * @param keyPass {@link char[]}, key 密码
     * @return {@link PrivateKey}
     * @throws UnrecoverableKeyException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws CertificateException
     * @throws KeyStoreException
     */
    PrivateKey getPrivateKey(KeyStore keystore, String alias, char[] keyPass)
        	throws UnrecoverableKeyException, NoSuchAlgorithmException, InvalidKeyException, 
        		CertificateException, KeyStoreException;
    
    /**
     * 从{@link keyStore}中提取{@link alias}的证书
     * @param keystore {@link KeyStore}
     * @param alias {@link String}, key的别名
     * @return {@link Certificate}, 可能返回null.
     * @throws KeyStoreException
     */
    X509Certificate getX509Certificate(KeyStore keystore, String alias)
        	throws KeyStoreException;
    
    /**
     * 从<Code>file</Code>中加载x509证书
     * @param file {@link File}, cer证书文件
     * @return {@link X509Certificate}
     */
    X509Certificate loadX509Certificate(File file)
            throws IOException, NoSuchProviderException, CertificateException;


    /**
     * 从<code>cerFile</code>中加载x509证书
     * @param cerFile {@link String}, 以.cer扩展名的证书文件
     * @return {@link X509Certificate}
     */
    default X509Certificate loadX509Certificate(String cerFile)
            throws IOException, NoSuchProviderException, CertificateException{
        Objects.requireNonNull(cerFile, "\"cerFile\" cannot be null.");
        return this.loadX509Certificate(new File(cerFile));
    }
    
    /**
     * 从{@code keyStoreFile}加载KeyStore
     * @param keyStoreFile {@link File}, keystore文件
     * @param storePass {@link char[]}，打开keystore文件的密钥
     * @return {@link KeyStore}
     * @throws KeyStoreException
     * @throws IOException
     * @throws NoSuchProviderException
     * @throws CertificateException
     * @throws NoSuchAlgorithmException
     */
    KeyStore loadKeyStore(File keyStoreFile, char[] storePass) 
    	throws KeyStoreException,  IOException, NoSuchProviderException, 
    		CertificateException, NoSuchAlgorithmException;
}
